﻿using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;

namespace Sex
{
    public partial class Sex : System.Web.UI.Page
    {
        public class MyList : Dictionary<string, string[]>
        {
            const string PrefixForHeaderRow = "#!#";
            const string PrefixForColspan = "#>#";
            const string strStringDelimiter = ", ";
            const bool DisplayBoolAsBullet = false;
            const bool ThumbsImageNoScaleWhenSmaller = true;

            // inserted tex in lists
            protected const string strExtraMenuPoint = "--see extra menu point--";
            protected const string strComplexType = "--complex type--";
            protected const string strNotAvailable = "--not available--";
            protected const string strSeeObject = "--see detailed Object--";
            protected const string strNoData = "--no data--";
            protected const string strRequiresPipelineMode = "--requires internal pipeline mode--";
            protected const string strRequiresFramework4 = "--requires framework 4.0--";
            protected const string strDemoEntry = "--demo entry--";
            protected const string strDemoVariableName = "Demo-Variable";

            Control ThumbTemplate(string ObjectCode, string Title, bool ShowCentered, int ThumbDimension)
            {
                Table t = new Table();
                // Object
                TableRow tr = new TableRow();
                TableCell tc = new TableCell();
                tc.VerticalAlign = VerticalAlign.Top;
                tc.HorizontalAlign = HorizontalAlign.Left;
                tc.Controls.Add(new LiteralControl(ObjectCode));
                tc.Width = ThumbDimension;
                tc.Height = ThumbDimension;
                tc.BorderWidth = 1;
                tc.BorderColor = System.Drawing.Color.Gray;
                if (ShowCentered) tc.VerticalAlign = VerticalAlign.Middle;
                if (ShowCentered) tc.HorizontalAlign = HorizontalAlign.Center;
                tr.Cells.Add(tc);
                t.Rows.Add(tr);
                // Title
                tr = new TableRow();
                tc = new TableCell();
                tc.Controls.Add(new LiteralControl(Title));
                tc.BorderWidth = 1;
                tc.BorderColor = System.Drawing.Color.Gray;
                tc.VerticalAlign = VerticalAlign.Middle;
                tc.HorizontalAlign = HorizontalAlign.Center;
                tr.Cells.Add(tc);
                t.Rows.Add(tr);
                return t;
            }
            string[] MyValues = new string[] { strDemoVariableName, strExtraMenuPoint, strComplexType, strNotAvailable, strSeeObject, strNoData, strRequiresPipelineMode, strRequiresFramework4, strDemoEntry };
            string Title;
            string TitleFirstColumn;
            string[] TitleOtherColumns;
            State MyState;

            public MyList(State MyState, string Title)
            {
                this.MyState = MyState;
                this.Title = Title;
                this.TitleFirstColumn = null;
                this.TitleOtherColumns = null;
            }
            public MyList(State MyState, string Title, string TitleFirstColumn, string[] TitleOtherColumns)
            {
                this.MyState = MyState;
                this.Title = Title;
                this.TitleFirstColumn = TitleFirstColumn;
                this.TitleOtherColumns = TitleOtherColumns;
            }
            public MyList(State MyState)
            {
                this.MyState = MyState;
                this.Title = null;
            }
            public void Add(string Key, string[] Values)
            {
                base.Add(PrefixForHeaderRow + Key, Values);
            }
            public void Add(string Key, string Value)
            {
                Add(Key, new string[] { Value });
            }
            public void AddTitle(string Title, int Colspan)
            {
                string[] Values = new string[Colspan];
                for (int i = 0; i < Values.Length; i++)
                {
                    Values[i] = PrefixForColspan;
                }
                Add(Title, PrefixForColspan+Colspan);
            }
            private Control GetDataSorted(bool Sort)
            {
                Panel p = new Panel();
                if (!string.IsNullOrEmpty(Title))
                {
                    LiteralControl l = new LiteralControl("<h3>" + Title + "</h3>\r\n");
                    p.Controls.Add(l);
                }
                Table t = new Table();
                if (TitleFirstColumn != null)
                {
                    for (int i = 0; i < TitleOtherColumns.Length; i++)
                    {
                        TitleOtherColumns[i] = PrefixForHeaderRow + TitleOtherColumns[i];
                    }
                    t.Rows.Add(GetRow(TitleFirstColumn, TitleOtherColumns));
                }
                switch (Sort)
                {
                    case true:
                        SortedList<string, string[]> sl = new SortedList<string, string[]>(this);
                        foreach (KeyValuePair<string, string[]> kvp in sl)
                        {
                            t.Rows.Add(GetRow(kvp.Key, kvp.Value));
                        }
                        break;
                    case false:
                        foreach (KeyValuePair<string, string[]> kvp in this)
                        {
                            t.Rows.Add(GetRow(kvp.Key, kvp.Value));
                        }
                        break;
                }
                p.Controls.Add(t);
                return p;
            }
            public Control GetDataSorted()
            {
                return GetDataSorted(true);
            }
            public Control GetData()
            {
                return GetDataSorted(false);
            }
            /*
                Panel p = new Panel();
                if (!string.IsNullOrEmpty(Title))
                {
                    LiteralControl l = new LiteralControl("<h3>" + Title + "</h3>\r\n");
                    p.Controls.Add(l);
                }
                Table t = new Table();
                if (TitleFirstColumn != null)
                {
                    for (int i = 0; i < TitleOtherColumns.Length; i++)
                    {
                        TitleOtherColumns[i] = PrefixForHeaderRow + TitleOtherColumns[i];
                    }
                    t.Rows.Add(GetRow(TitleFirstColumn, TitleOtherColumns));
                }
                foreach (KeyValuePair<string, string[]> kvp in this)
                {
                    t.Rows.Add(GetRow(kvp.Key, kvp.Value));
                }
                p.Controls.Add(t);
                return p;
            */
            public Control GetThumbs(int ThumbDimension, int ThumbCols)
            {
                Panel p = new Panel();
                if (!string.IsNullOrEmpty(Title))
                {
                    LiteralControl l = new LiteralControl("<h3>" + Title + "</h3>\r\n");
                    p.Controls.Add(l);
                }
                Table t = new Table();
                int Index = 0;
                TableRow tr = new TableRow();
                foreach (KeyValuePair<string, string[]> kvp in this)
                {
                    string PathAbs = kvp.Key.Substring(3);
                    string PathRel = kvp.Value[0];
                    string Mode = kvp.Value[1];
                    E_ObjectCommand ModeToStart = (E_ObjectCommand)int.Parse(Mode);
                    string Type = kvp.Value[2];
                    FileGroup.Type FileType = (FileGroup.Type)int.Parse(Type);
                    string TitleObject = Path.GetFileName(PathRel);
                    string Template = "";

                    TableCell tc = new TableCell();
                    bool ShowObject = true;
                    bool ShowCentered = true;
                    switch (ModeToStart)
                    {
                        default:
                        case E_ObjectCommand.CODE:
                        case E_ObjectCommand.DIRECTORY:
                        case E_ObjectCommand.DOWNLOAD:
                        case E_ObjectCommand.EXIF:
                        case E_ObjectCommand.NONE:
                        case E_ObjectCommand.PERMISSIONS:
                        case E_ObjectCommand.SPECIAL:
                        case E_ObjectCommand.HEX:
                        case E_ObjectCommand.THUMBS:
                            ShowObject = false;
                            break;
                        case E_ObjectCommand.EMBED:
                            Img img = new Img(PathAbs);
                            const bool ThumbsImageNoScaleWhenSmaller = true;
                            int x = img.x;
                            int y = img.y;
                            int px;
                            int py;
                            // scaling
                            if ((x < ThumbDimension) && (y < ThumbDimension) && ThumbsImageNoScaleWhenSmaller)
                            {
                                px = x;
                                py = y;
                            }
                            else
                            {
                                if (x == y) { px = ThumbDimension; py = ThumbDimension; }
                                else if (x > y) { px = ThumbDimension; py = (int)((1.0 * ThumbDimension / x) * y); }
                                else { py = ThumbDimension; px = (int)((1.0 * ThumbDimension / y) * x); }
                            }
                            Template = MediaTemplates.InstantiateTemplate(0, px.ToString(), py.ToString(), PathRel);
                            break;
                        case E_ObjectCommand.FRAME:
                            Template = MediaTemplates.InstantiateTemplate(11, ThumbDimension.ToString(), ThumbDimension.ToString(), PathRel);
                            break;
                        // case E_ObjectCommand.NEWWIN:
                            //     Template = MediaTemplates.InstantiateTemplate(11, ThumbDimension.ToString(), ThumbDimension.ToString(), PathRel);
                        // break;
                        case E_ObjectCommand.LINK:
                            switch (FileType)
                            {
                                case FileGroup.Type.AUDIO:
                                case FileGroup.Type.AUDVID:
                                case FileGroup.Type.VIDEO:
                                    Template = "<div style='font-size:32pt;color:gray;'>&#x266b;</div>" + MediaTemplates.InstantiateTemplate(12, ThumbDimension.ToString(), ThumbDimension.ToString(), PathRel);
                                    break;
                                default:
                                case FileGroup.Type.APPLI:
                                case FileGroup.Type.APPLIEXE:
                                case FileGroup.Type.BINARY:
                                case FileGroup.Type.CODE:
                                case FileGroup.Type.CODEEXE:
                                case FileGroup.Type.EXIF:
                                case FileGroup.Type.IMAGE:
                                case FileGroup.Type.INLINE:
                                case FileGroup.Type.NOTYPE:
                                case FileGroup.Type.OTHER:
                                    ShowObject = false;
                                    break;
                            }
                            break;
                        case E_ObjectCommand.TEXT:
                            Template = Untag(SplitLongLines(File.ReadAllText(PathAbs)));
                            ShowCentered = false;
                            break;
                        case E_ObjectCommand.INLINE:
                            Template = File.ReadAllText(PathAbs);
                            break;
                    }
                    if (ShowObject)
                    {
                        tc.Controls.Add(ThumbTemplate(Template, TitleObject, ShowCentered, ThumbDimension));
                        tr.Cells.Add(tc);
                        Index++;
                        if (Index % ThumbCols == 0)
                        {
                            t.Rows.Add(tr);
                            tr = new TableRow();
                        }
                    }
                }
                if (tr.Cells.Count > 0)
                    t.Rows.Add(tr);
                p.Controls.Add(t);
                return p;
            }
            private string MarkMyValues(string Text)
            {
                if (string.IsNullOrEmpty(Text)) return "";
                for (int i = 0; i < MyValues.Length; i++)
                {
                    if (Text.Contains(MyValues[i]))
                    {
                        Text = Text.Replace(MyValues[i], "<span class='MyValue'>" + MyValues[i] + "</span>");
                    }
                }
                return Text;
            }
            private TableCell GetCell(string Content)
            {
                TableCell tc = new TableCell();
                Label lb = new Label();
                string c = Content == null ? "" : Content.ToString();
                bool isHeader = false;
                if (c.StartsWith(PrefixForHeaderRow))
                {
                    isHeader = true;
                    c = c.Substring(PrefixForHeaderRow.Length);
                }
                if (c.ToLower() == "false") c = "<span class='LB'>" + (DisplayBoolAsBullet ? "&#x25cb;" : "-") + "</span>";
                if (c.ToLower() == "true") c = "<span class='LB'>" + (DisplayBoolAsBullet ? "&#x25cf;" : "+") + "</span>";
                lb.Text = c;
                tc.Controls.Add(lb);
                tc.VerticalAlign = VerticalAlign.Top;
                tc.CssClass = isHeader ? "LH" : "";
                return tc;
            }
            private TableRow GetRow(string Left, string Right)
            {
                return GetRow(Left, new string[] { Right });
            }
            private TableRow GetRow(string Left, string[] Right)
            {
                TableRow tr = new TableRow();
                TableCell tc = GetCell(Left);
                if (Right!=null)
                    if (Right[0]!=null)
                        if (Right[0].StartsWith(PrefixForColspan))
                        {
                            tc.ColumnSpan = int.Parse(Right[0].Remove(0, PrefixForColspan.Length));
                            tr.Cells.Add(tc);
                            return tr;
                        }
                tr.Cells.Add(tc);
                for (int i = 0; i < Right.Length; i++)
                {
                    tr.Cells.Add(GetCell(MarkMyValues(Right[i])));
                }
                return tr;
            }
            protected string FormatMyText(string Text)
            {
                return "<span class='MyValue'>" + Text + "</span>";
            }
            protected string FormatMyKey(string Text)
            {
                return "<span class='LH'>" + Text + "</span>";
            }
            protected string GetDictionary(System.Collections.IDictionary id)
            {
                string dictionary = "";
                foreach (System.Collections.DictionaryEntry Entry in id)
                {
                    dictionary += FormatMyKey(Entry.Key.ToString()) + FormatMyText("=") + Entry.Value + "<br/>";
                }
                return dictionary;
            }
            protected string GetNameValueCollection(System.Collections.Specialized.NameValueCollection nvc)
            {
                string result = "";
                for (int i = 0; i < nvc.Count; i++)
                {
                    result += FormatMyKey(nvc.Keys[i]) + FormatMyText("=") + Untag(nvc[i]) + "<br/>";
                }
                return result;
            }
            protected string GetStringArray(string[] StringArray)
            {
                string s = "";
                if (StringArray == null) return "";
                if (StringArray.Length == 0) return "";
                for (int i = 0; i < StringArray.Length; i++)
                {
                    if (StringArray[i] == "") continue;
                    s += (s == "" ? "" : strStringDelimiter) + StringArray[i];
                }
                return Untag(s);
            }
            protected string GetArrayList(ArrayList al)
            {
                string strAl = "";
                if (al == null) return strNoData;
                for (int i = 0; i < al.Count; i++)
                {
                    strAl += al[i] + "<br/>";
                }
                return strAl;
            }
            protected string SplitLongLine(string Text)
            {
                int Length = Text.Length;
                if (Length <= MyState.MaxLineLength) return Text;
                string NewText = "";
                int Parts = Text.Length / MyState.MaxLineLength;
                for (int i = 0; i <= Parts; i++)
                {
                    int Start = i * MyState.MaxLineLength; if (Start > Length) break;
                    int LengthOfPart = MyState.MaxLineLength;
                    if ((Start + LengthOfPart) > Length) LengthOfPart = Length - Start;
                    NewText += Text.Substring(i * MyState.MaxLineLength, LengthOfPart) + " ";
                }
                return NewText;
            }
            protected string SplitLongLines(string Text)
            {
                Text = Regex.Replace(Text, "  ", " ");
                string[] Lines = Text.Split(new char[] { ' ' });
                Text = "";
                for (int i = 0; i < Lines.Length; i++)
                {
                    Text += SplitLongLine(Lines[i]) + " ";
                    if (i >= MyState.MaxLineCount)
                    {
                        Text += "...";
                        break;
                    }
                }
                return Text;
            }
        }
    }
}